import java.util.*;
import java.util.stream.Collectors;

public class Leetcode652 {

    Map<Integer, TreeNode> map = new HashMap<>();

    Map<Integer, TreeNode> res = new HashMap<>();


    public List<TreeNode> findDuplicateSubtrees(TreeNode root) {
        dfs(root);

        return new ArrayList<>(res.values());
    }

    private void dfs(TreeNode root) {
        if (root == null) {
            return;
        }
        dfs(root.left);
        dfs(root.right);
        int hash = hash(root);
        if (map.containsKey(hash)&&equal(root, map.get(hash))) {
            res.put(hash, root);
        } else {
            map.put(hash, root);
        }
    }

    private static int hash(TreeNode root) {
        if (root == null) {
            return 0;
        }

        return root.val + hash(root.left) + hash(root.right);
    }

    private static boolean equal(TreeNode root1, TreeNode root2) {
        if (root1 == null && root2 == null) {
            return true;
        }
        if (root1 == null || root2 == null) {
            return false;
        }

        return root1.val == root2.val && equal(
                root1.left,
                root2.left
        ) && equal(
                root1.right,
                root2.right
        );
    }


}
